package com.hzins.scher.schedulerholder;

import java.util.Date;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.hzins.scher.constant.ScherConstant;
import com.hzins.scher.core.JobTarget;
import com.hzins.scher.core.SchedulerHolder;
import com.hzins.scher.exception.ScherException;

@Component
public class ScherSchedulerHolder implements SchedulerHolder {

	@Resource
	private Scheduler scheduler;
	private String schedulerName;
	private Logger logger = LoggerFactory.getLogger(getClass());

	@PostConstruct
	public void initSchedulerName() {
		try {
			this.scheduler.clear();
			this.schedulerName = this.scheduler.getSchedulerName();
			this.logger.debug(">>>>>>> schedulerName:{}", this.schedulerName + ">>>>>>>>>");
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	public String getSchedulerName() {
		return this.schedulerName;
	}

	public void createJobInImmediately(String jobName, String groupName) {
		JobKey jobKey = JobKey.jobKey(jobName, groupName);
		try {
			this.scheduler.triggerJob(jobKey);
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	public void createJob(String jobName, String groupName,
			String cronExpression, boolean jobDurability, boolean jobRecover,JobTarget jobTarget) {
		removeJob(jobName, groupName);
		JobDetail jobDetail = JobBuilder
				.newJob(ScherConstant.DEFAULT_JOB_CLASS)
				.withIdentity(jobName, groupName).requestRecovery(jobRecover)
				.storeDurably(jobDurability).build();
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity(jobName, groupName)
				.withSchedule(CronScheduleBuilder.cronSchedule(cronExpression))
				.build();
		setJobDataMap(jobDetail, jobTarget);
		try {
			this.scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	private void setJobDataMap(JobDetail jobDetail, JobTarget jobTarget) {
		jobTarget.getMethodParameters().put("_targetBeanName",
				jobTarget.getTargetBeanName());
		jobTarget.getMethodParameters().put("_targetMethodName",
				jobTarget.getTargetMethodName());
		jobDetail.getJobDataMap().putAll(jobTarget.getMethodParameters());
	}

	public void createJob(String jobName, String groupName, Date startTime,
			boolean jobDurability, boolean jobRecover, JobTarget jobTarget) {
		removeJob(jobName, groupName);
		JobDetail jobDetail = JobBuilder
				.newJob(ScherConstant.DEFAULT_JOB_CLASS)
				.withIdentity(jobName, groupName).requestRecovery(jobRecover)
				.storeDurably(jobDurability).build();
		Trigger trigger = TriggerBuilder.newTrigger()
				.withIdentity(jobName, groupName).startAt(startTime).build();
		setJobDataMap(jobDetail, jobTarget);
		try {
			this.scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	public void createJob(JobDetail jobDetail, Trigger trigger) {
		try {
			this.scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	public void createJob(String jobName, String groupName, Date startTime,
			long repeatInterval, int repeatCount, boolean jobDurability,
			boolean jobRecover, JobTarget jobTarget) {
		removeJob(jobName, groupName);
		JobDetail jobDetail = JobBuilder
				.newJob(ScherConstant.DEFAULT_JOB_CLASS)
				.withIdentity(jobName, groupName).requestRecovery(jobRecover)
				.storeDurably(jobDurability).build();
		Trigger trigger = TriggerBuilder
				.newTrigger()
				.withIdentity(jobName, groupName)
				.startAt(startTime)
				.withSchedule(
						SimpleScheduleBuilder.simpleSchedule()
								.withIntervalInMilliseconds(repeatInterval)
								.withRepeatCount(repeatCount)).build();
		setJobDataMap(jobDetail, jobTarget);
		try {
			this.scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}

	public void removeJob(String jobName, String groupName) {
		try {
			this.scheduler.deleteJob(new JobKey(jobName, groupName));
		} catch (SchedulerException e) {
			throw new ScherException(e);
		}
	}
}
